package com.csw.android.ffmpegtest.ui.section8

import android.Manifest
import android.graphics.ImageFormat
import android.hardware.camera2.CameraCharacteristics
import android.media.ImageReader
import android.opengl.GLSurfaceView
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.view.View
import com.csw.android.dev_utils.utils.ToastUtils
import com.csw.android.ffmpegtest.R
import com.csw.android.ffmpegtest.camera.CameraController
import com.csw.android.ffmpegtest.camera.CameraSelector
import com.csw.android.ffmpegtest.databinding.LayoutSection801Binding
import com.csw.android.ffmpegtest.gl.Section802Renderer
import com.csw.android.ffmpegtest.ui.base.DataBindingFragment
import com.tbruyelle.rxpermissions3.RxPermissions

/**
 * 801中将采集的图象转rgb是在线程中，性能有限，画面卡顿，计算工作主要是cpu在做，这里将yuv数据直接传入opengl中，
 * 通过片段着色器，让数据运算在gpu中执行，实现高效率刷新摄像头预览画面
 *
 * 这里摄像头采集的数据我们以YUV的形式返回，进行预览
 * https://www.jianshu.com/p/39cde80d60e2
 */
class Section802 : DataBindingFragment<LayoutSection801Binding>() {

    private var handlerThread: HandlerThread? = null
    private val imageFormat = ImageFormat.YUV_420_888

    private val facing = CameraCharacteristics.LENS_FACING_FRONT

    //    private val facing = CameraCharacteristics.LENS_FACING_BACK
    private var renderer: Section802Renderer? = null
    private var cameraController: CameraController? = null
    private var previewCameraId: String? = null
    private var imageReader: ImageReader? = null


    override fun getContentViewID(): Int {
        return R.layout.layout_section_801
    }

    override fun initView(rootView: View, savedInstanceState: Bundle?) {
        super.initView(rootView, savedInstanceState)
        dataBinding?.glSurfaceView?.run {
            setEGLContextClientVersion(3)
            setRenderer(Section802Renderer().apply {
                renderer = this
            })
            renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
        }
    }


    override fun initListener() {
        super.initListener()
        handlerThread?.quit()
        handlerThread = HandlerThread("图片接收处理线程").apply {
            start()
        }
        imageReader = ImageReader.newInstance(
            1080,
            1920,
            imageFormat,
            2
        ).apply {
            setOnImageAvailableListener({ reader ->
                reader?.run {
                    acquireLatestImage()?.run {
                        try {
                            if (format == imageFormat && planes.size == 3) {
                                //yuv420采样，返回的数据是yuv三个平面的数据(4:1:1)
                                val yPlane = planes[0]
                                val uPlane = planes[1]
                                val vPlane = planes[2]
                                val yBuffer = yPlane.buffer
                                val uBuffer = uPlane.buffer
                                val vBuffer = vPlane.buffer
                                val width = yPlane.rowStride / yPlane.pixelStride//一行多少像素
                                val height = yBuffer.limit() / yPlane.rowStride//总共多少行
                                val yData = ByteArray(width * height)
                                val uData = ByteArray(width * height / 4)
                                val vData = ByteArray(width * height / 4)
                                if (yPlane.pixelStride == 1) {
                                    yBuffer.get(yData)
                                } else {
                                    for (i in yData.indices) {
                                        yData[i] =
                                            yBuffer[i * yPlane.pixelStride]
                                    }
                                }
                                if (uPlane.pixelStride == 1) {
                                    uBuffer.get(uData)
                                } else {
                                    for (i in uData.indices) {
                                        uData[i] =
                                            uBuffer[i * uPlane.pixelStride]
                                    }
                                }
                                if (vPlane.pixelStride == 1) {
                                    vBuffer.get(vData)
                                } else {
                                    for (i in vData.indices) {
                                        vData[i] =
                                            vBuffer[i * vPlane.pixelStride]
                                    }
                                }
                                renderer?.updatePicture(width, height, yData, uData, vData)
                                dataBinding?.glSurfaceView?.requestRender()
                            }
                        } catch (e: Exception) {
                            e.printStackTrace()
                        } finally {
                            close()
                        }
                    }
                }
            }, Handler(handlerThread!!.looper))
        }
    }

    override fun initData() {
        super.initData()
        val b_100: Byte = -100
        val i_100 = b_100.toInt()
        val i156 = 0xFF and i_100
        val b156 = i156.toByte()

        RxPermissions(this).request(
            Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO
        ).subscribe {
            if (it) {
                dataBinding?.root?.visibility = View.VISIBLE
                initCamera()
            } else {
                activity?.finish()
            }
        }
    }

    private fun initCamera() {
        val surface = imageReader?.surface ?: return
        activity?.let { context ->
            CameraSelector().let { selector ->
                selector.facing = this@Section802.facing
                selector.imageFormat = this@Section802.imageFormat
                selector.selectCamera()?.let { cameraId ->
                    previewCameraId = cameraId
                    cameraController = CameraController().apply {
                        connectToCamera(context, cameraId)
                        addSurface(
                            cameraId,
                            surface
                        )
                    }
                    //根据摄像头方向，对画面进行角度矫正
                    renderer?.setRotate(selector.selectedCameraOrientation.toFloat())
                    return
                }
            }
            ToastUtils.showShort("无匹配摄像头")
        }
    }

    override fun onResume() {
        super.onResume()
        dataBinding?.glSurfaceView?.onResume()
    }

    override fun onPause() {
        dataBinding?.glSurfaceView?.onPause()
        super.onPause()
    }

    override fun onDestroyView() {
        cameraController?.release()
        handlerThread?.quitSafely()
        renderer = null
        super.onDestroyView()
    }
}